/**
 * Copyright [2019] [LiBo/Alex of copyright liboware@gmail.com ]
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hyts.monitor.profile.loader.item;

import com.hyts.monitor.profile.config.ConfigKey;
import com.hyts.monitor.profile.config.ProfilerConfig;
import com.hyts.monitor.profile.loader.AbtractProfilerLoader;
import com.hyts.monitor.profile.model.Attribute;
import com.hyts.monitor.profile.model.Command;
import com.hyts.monitor.profile.model.Connector;
import com.hyts.monitor.profile.model.Profiler;
import com.hyts.reflection.b11_9.FieldAccess;
import com.sun.org.apache.xerces.internal.impl.PropertyManager;
import jdk.internal.util.xml.impl.Input;

import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;

/**
 * @project-name:coffice-toolbox
 * @package-name:com.hyts.monitor.profile.loader
 * @author:LiBo/Alex
 * @create-date:2019-08-06 16:34
 * @copyright:libo-alex4java
 * @email:liboware@gmail.com
 * @description: propertiesProfilerLoader读取操作服务
 */
public class PropertiesProfilerLoader extends AbtractProfilerLoader {

    /**
     * 系统操作服务
     */
    private Logger logger = Logger.getLogger(PropertiesProfilerLoader.class.getName());

    /**
     * 操作信息对象配置对象
     */
    Properties propertie = new Properties();


    private static final String[] SET_TOKEN_START_END_TOKEN = {"(",")",","};


    /**
     * 两种dest
     * 暂时不考虑环境变量制定以及系统参数制定方式
     * (默认级别高) 1.user.dir/config/profiler.properties
     * (1.不存在情况下才回去所搜)2.user.home/config/profiler.properties
     *
     * @return
     */
    @Override
    public boolean preCheckUseDefault() {
        //校验是否存在改文件
        boolean useDefaultConfig = false;
        if (Files.exists(Paths.get(ProfilerConfig.FileConfig.DEFAULT_CONFIG_PATH_02))) {
            loadProperties(ProfilerConfig.FileConfig.DEFAULT_CONFIG_PATH_02);
        } else if (Files.exists(Paths.get(ProfilerConfig.FileConfig.DEFAULT_CONFIG_PATH_01))) {
            loadProperties(ProfilerConfig.FileConfig.DEFAULT_CONFIG_PATH_01);
        } else {
            try {
                propertie.load(PropertiesProfilerLoader.class.getClassLoader().
                        getResourceAsStream(ProfilerConfig.FileConfig.DEFAULT_CONFIG_NAME));
            } catch (IOException e) {
                logger.warning("系统无法获取相关profiler.properties配置文件,采用默认配置方式!!!");
                useDefaultConfig = true;
            }
        }
        return useDefaultConfig;
    }

    /**
     * 加载command配置命令服务操作工具处理器-
     * 暂时不能信自定义和定制化操作
     * 参考默认机制
     */
    @Override
    public void loadCommandConfig(ConfigKey configKey, List<String> attribute) {
        //循环遍历功能实现 - 直接利用反射功能的实现操作
        injectProperties(profiler.getCommand(),attribute,configKey);
    }
    /**
     * connector服务操作处理
     * 因为字段为简单单对象实现对象实例
     */
    @Override
    public void loadConnectorConfig(ConfigKey configKey, List<String> attribute) {
        //循环遍历功能实现 - 直接利用反射功能的实现操作
        injectProperties(profiler.getConnector(),attribute,configKey);
    }

    @Override
    public void loadAttributeConfig(ConfigKey configKey, List<String> attribute) {
        //循环遍历功能实现 - 直接利用反射功能的实现操作
        injectProperties(profiler.getAttribute(),attribute,configKey);

    }

    @Override
    public void loadFilterConfig(ConfigKey configKey, List<String> attribute) {
        //循环遍历功能实现 - 直接利用反射功能的实现操作
        injectProperties(profiler.getFilter(),attribute,configKey);
    }

    @Override
    public void loadScopeConfig(ConfigKey configKey, List<String> attribute) {
        //循环遍历功能实现 - 直接利用反射功能的实现操作
        injectProperties(profiler.getScope(),attribute,configKey);
    }

    @Override
    public int order() {
        return 2;
    }

    /**
     * 加载配置
     * @param path
     */
    void loadProperties(String path) {
        FileInputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream(Paths.get(path).toFile());
            propertie.load(fileInputStream);
        } catch (java.io.IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 注入属性
     * @param param
     * @param attribute
     * @param configKey
     * @param <T>
     * @return
     */
    <T> T injectProperties(T param, List<String> attribute,ConfigKey configKey) {
        //循环遍历功能实现 - 直接利用反射功能的实现操作
        attribute.parallelStream().filter(param0 -> param0 != null &&
                param0.length() != 0).forEach(param1 -> {
            try {
                Field field = param.getClass().getDeclaredField(param1);
                if (!field.isAccessible()) {
                    field.setAccessible(true);
                }
                String value = propertie.getProperty(ProfilerConfig.FileConfig.CONFIG_KEY_PREFIX + configKey + "." + param1);
                if (value != null && value.length() != 0) {
                    if(field.getType() == AtomicBoolean.class){
                        field.set(param,new AtomicBoolean(Boolean.valueOf(value)));
                    }else if(field.getType() == String.class){
                        //判断是否属于set集合的注入方式
                        field.set(param, value);
                    }else if(field.getType() == HashSet.class || field.getType() == Set.class){
                        if(value.startsWith(SET_TOKEN_START_END_TOKEN[0]) &&
                                value.endsWith(SET_TOKEN_START_END_TOKEN[1])){
                            StringTokenizer stringTokenizer = new StringTokenizer(value.substring(1,value.length()-1),SET_TOKEN_START_END_TOKEN[2]);
                            Set<String> stringSet = (Set)field.get(param);
                            while(stringTokenizer.hasMoreElements()){
                                stringSet.add((String) stringTokenizer.nextElement());
                            }
                            field.set(param, stringSet);
                        }
                    }
                }
            } catch (NoSuchFieldException | IllegalAccessException e) {
                e.printStackTrace();
            }
        });
        return param;
    }

    public static void main(String[] args){
        PropertiesProfilerLoader propertiesProfilerLoader = new PropertiesProfilerLoader();
        Profiler profiler = propertiesProfilerLoader.loadProfilerConfig();
        System.out.println(profiler);
        System.out.println(propertiesProfilerLoader.propertie);
    }

}
